package cn.coonu.common.calendar.lunar;

import java.io.Serializable;
import java.util.Calendar;
import java.util.GregorianCalendar;

/**
 * 中国农历
 * Created by joel on 2019/3/31.      1.2 stable
 *
 * @author joel
 */
public final class LunarCalendar implements Serializable {

    // ------------------------ 常量定义 --------------------------------

    /**
     * 支持的最小年份
     */
    public final static int MINI_YEAR = 1850;
    /**
     * 支持的最大年份
     */
    public final static int MAX_YEAR = 2150;
    /**
     * 10天干
     * '甲', '乙', '丙', '丁', '戊', '己', '庚', '辛', '壬', '癸'
     */
    private static final char[] LunarGan = {'\u7532', '\u4e59', '\u4e19', '\u4e01', '\u620a', '\u5df1', '\u5e9a',
            '\u8f9b', '\u58ec', '\u7678'};
    /**
     * 12地支
     * '子', '丑', '寅', '卯', '辰', '巳', '午', '未', '申', '酉', '戌', '亥'
     */
    private static final char[] LunarZhi = {'\u5b50', '\u4e11', '\u5bc5', '\u536f', '\u8fb0', '\u5df3', '\u5348',
            '\u672a', '\u7533', '\u9149', '\u620c', '\u4ea5'};
    /**
     * 12生肖
     * '鼠', '牛', '虎', '兔', '龍', '蛇', '馬', '羊', '猴', '雞', '犬', '豬'
     */
    private static final char[] LunarAnimalName = {'\u9f20', '\u725b', '\u864e', '\u5154', '\u9f8d', '\u86c7',
            '\u99ac', '\u7f8a', '\u7334', '\u96de', '\u72ac', '\u8c6c'};
    /**
     * 农历年份名
     * '〇', '一', '二', '三', '四', '五', '六', '七', '八', '九'
     */
    private static final char[] LunarYearName = {'\u3007', '\u4e00', '\u4e8c', '\u4e09', '\u56db', '\u4e94',
            '\u516d', '\u4e03', '\u516b', '\u4e5d'};
    /**
     * 农历月份名
     * '正', '二', '三', '四', '五', '六', '七', '八', '九', '十', '冬', '腊'
     */
    private static final char[] LunarMonthName = {'\u6b63', '\u4e8c', '\u4e09', '\u56db', '\u4e94', '\u516d',
            '\u4e03', '\u516b', '\u4e5d', '\u5341', '\u51ac', '\u814a'};
    /**
     * 农历日期名
     * "初一", "初二", "初三", "初四", "初五", "初六", "初七", "初八", "初九",
     * "初十", "十一", "十二", "十三", "十四", "十五", "十六", "十七", "十八", "十九", "二十", "廿一", "廿二",
     * "廿三", "廿四", "廿五", "廿六", "廿七", "廿八", "廿九", "三十"
     */
    private static final String[] LunarDayName = {"\u521d\u4e00", "\u521d\u4e8c", "\u521d\u4e09", "\u521d\u56db",
            "\u521d\u4e94", "\u521d\u516d", "\u521d\u4e03", "\u521d\u516b", "\u521d\u4e5d", "\u521d\u5341",
            "\u5341\u4e00", "\u5341\u4e8c", "\u5341\u4e09", "\u5341\u56db", "\u5341\u4e94", "\u5341\u516d",
            "\u5341\u4e03", "\u5341\u516b", "\u5341\u4e5d", "\u4e8c\u5341", "\u5eff\u4e00", "\u5eff\u4e8c",
            "\u5eff\u4e09", "\u5eff\u56db", "\u5eff\u4e94", "\u5eff\u516d", "\u5eff\u4e03", "\u5eff\u516b",
            "\u5eff\u4e5d", "\u4e09\u5341"};
    /**
     * 农历信息.<br>
     * 每个数组的第一个数表示该年闰月月份，为0表示不闰月<br>
     * 数组中其他数表示该月初一对应的公历日期<br>
     */
    private final static short[][] LUNAR_INFO = {
            {0, 212, 314, 412, 512, 610, 709, 808, 906, 1005, 1104, 1204, 1302},       // 1850
            {8, 201, 303, 402, 501, 531, 629, 728, 827, 925, 1024, 1123, 1222, 1321},  // 1851
            {0, 220, 321, 331, 419, 519, 618, 717, 815, 914, 1013, 1112, 1211, 1309},  // 1852
            {0, 208, 310, 408, 508, 607, 706, 805, 903, 1003, 1101, 1201, 1230},       // 1853
            {7, 129, 227, 329, 427, 527, 625, 725, 824, 922, 1022, 1120, 1220, 1318},  // 1854
            {0, 217, 318, 416, 516, 614, 714, 813, 911, 1011, 1110, 1209, 1308},       // 1855
            {0, 206, 307, 405, 504, 603, 702, 801, 830, 929, 1029, 1128, 1227},        // 1856
            {5, 126, 224, 326, 424, 523, 622, 721, 820, 918, 1018, 1116, 1216, 1315},  // 1857
            {0, 214, 315, 414, 513, 611, 711, 809, 907, 1007, 1106, 1205, 1304},       // 1858
            {0, 203, 305, 403, 503, 601, 630, 730, 828, 926, 1026, 1124, 1224},        // 1859
            {3, 123, 222, 322, 421, 521, 619, 718, 817, 915, 1014, 1113, 1212, 1311},  // 1860
            {0, 210, 311, 410, 510, 608, 708, 806, 905, 1004, 1103, 1202, 1231},       // 1861
            {8, 130, 301, 330, 429, 528, 627, 727, 825, 924, 1023, 1122, 1221, 1319},  // 1862
            {0, 218, 319, 418, 518, 616, 716, 814, 913, 1013, 1111, 1211, 1309},       // 1863
            {0, 208, 308, 406, 506, 604, 704, 802, 901, 1001, 1030, 1129, 1229, 1327}, // 1864
            {6, 127, 226, 327, 425, 525, 623, 723, 821, 920, 1020, 1118, 1218, 1317},  // 1865
            {0, 215, 317, 415, 514, 613, 712, 810, 909, 1009, 1107, 1207, 1306},       // 1866
            {0, 205, 306, 405, 504, 602, 702, 731, 829, 928, 1027, 1126, 1226},        // 1867
            {4, 125, 223, 324, 423, 522, 620, 720, 818, 916, 1016, 1114, 1214, 1313},  // 1868
            {0, 211, 313, 412, 512, 610, 709, 808, 906, 1005, 1104, 1203, 1302},       // 1869
            {10, 131, 302, 401, 501, 530, 629, 728, 827, 925, 1024, 1123, 1222, 1321}, // 1870
            {0, 219, 321, 420, 519, 618, 718, 816, 915, 1014, 1113, 1212, 1310},       // 1871
            {0, 209, 309, 408, 507, 606, 706, 804, 903, 1002, 1101, 1201, 1230},       // 1872
            {6, 129, 227, 328, 427, 526, 625, 724, 823, 922, 1021, 1120, 1220, 1318},  // 1873
            {0, 217, 318, 416, 516, 614, 714, 812, 911, 1010, 1109, 1209, 1308},       // 1874
            {0, 206, 308, 406, 505, 604, 703, 801, 831, 929, 1029, 1128, 1228},        // 1875
            {5, 126, 225, 326, 424, 523, 622, 721, 819, 918, 1017, 1116, 1216, 1314},  // 1876
            {0, 213, 315, 414, 513, 611, 711, 809, 907, 1007, 1105, 1205, 1303},       // 1877
            {0, 202, 304, 403, 502, 601, 630, 730, 828, 926, 1026, 1124, 1224},        // 1878
            {3, 122, 221, 323, 421, 521, 620, 719, 818, 916, 1015, 1114, 1213, 1312},  // 1879
            {0, 210, 311, 409, 509, 608, 707, 806, 905, 1004, 1103, 1202, 1231},       // 1880
            {7, 130, 228, 330, 428, 528, 626, 726, 825, 923, 1023, 1122, 1221, 1320},  // 1881
            {0, 218, 319, 418, 517, 616, 715, 814, 912, 1012, 1111, 1210, 1309},       // 1882
            {0, 208, 309, 407, 507, 605, 704, 803, 901, 1001, 1031, 1130, 1229},       // 1883
            {5, 128, 227, 327, 425, 525, 623, 722, 821, 919, 1019, 1118, 1217, 1316},  // 1884
            {0, 215, 317, 415, 514, 613, 712, 810, 909, 1008, 1107, 1206, 1305},       // 1885
            {0, 204, 306, 404, 504, 602, 702, 731, 829, 928, 1027, 1126, 1225},        // 1886
            {4, 124, 223, 325, 423, 523, 621, 721, 819, 917, 1017, 1115, 1215, 1313},  // 1887
            {0, 212, 313, 411, 511, 610, 709, 808, 906, 1005, 1104, 1203, 1302},       // 1888
            {12, 131, 302, 331, 430, 530, 628, 728, 826, 925, 1024, 1123, 1222, 1321}, // 1889
            {0, 219, 321, 419, 519, 617, 717, 816, 914, 1014, 1112, 1212, 1310},       // 1890
            {0, 209, 310, 409, 508, 607, 706, 805, 903, 1003, 1102, 1201, 1231},       // 1891
            {6, 130, 228, 328, 427, 526, 624, 724, 822, 921, 1021, 1119, 1219, 1318},  // 1892
            {0, 217, 318, 416, 516, 614, 713, 812, 910, 1010, 1108, 1208, 1307},       // 1893
            {0, 206, 307, 406, 505, 604, 703, 801, 831, 929, 1029, 1127, 1227},        // 1894
            {5, 126, 225, 326, 425, 524, 623, 722, 820, 919, 1018, 1117, 1216, 1315},  // 1895
            {0, 214, 314, 413, 513, 611, 711, 809, 907, 1007, 1105, 1205, 1303},       // 1896
            {0, 202, 303, 402, 502, 531, 630, 730, 828, 926, 1026, 1124, 1224},        // 1897
            {3, 122, 221, 322, 421, 520, 619, 719, 817, 916, 1015, 1114, 1213, 1312},  // 1898
            {0, 210, 312, 410, 510, 608, 708, 806, 905, 1005, 1103, 1203, 1301},       // 1899
            {8, 131, 301, 331, 429, 528, 627, 726, 825, 924, 1023, 1122, 1222, 1320},  // 1900
            {0, 219, 320, 419, 518, 616, 716, 814, 913, 1012, 1111, 1211, 1310},
            {0, 208, 310, 408, 508, 606, 705, 804, 902, 1002, 1031, 1130, 1230},
            {5, 129, 227, 329, 427, 527, 625, 724, 823, 921, 1020, 1119, 1219, 1317},
            {0, 216, 317, 416, 515, 614, 713, 811, 910, 1009, 1107, 1207, 1306},
            {0, 204, 306, 405, 504, 603, 703, 801, 830, 929, 1028, 1127, 1226},
            {4, 125, 223, 325, 424, 523, 622, 721, 820, 918, 1018, 1116, 1216, 1314},
            {0, 213, 314, 413, 512, 611, 710, 809, 908, 1007, 1106, 1205, 1304},
            {0, 202, 303, 401, 430, 530, 629, 728, 827, 925, 1025, 1124, 1223},
            {2, 122, 220, 322, 420, 519, 618, 717, 816, 914, 1014, 1113, 1213, 1311},
            {0, 210, 311, 410, 509, 607, 707, 805, 904, 1003, 1102, 1202, 1301},
            {6, 130, 301, 330, 429, 528, 626, 726, 824, 922, 1022, 1121, 1220, 1319},
            {0, 218, 319, 417, 517, 615, 714, 813, 911, 1010, 1109, 1209, 1307},
            {0, 206, 308, 407, 506, 605, 704, 802, 901, 930, 1029, 1128, 1227},
            {5, 126, 225, 327, 425, 525, 623, 723, 821, 920, 1019, 1117, 1217, 1315},
            {0, 214, 316, 414, 514, 613, 712, 811, 909, 1009, 1107, 1207, 1305},
            {0, 203, 304, 403, 502, 601, 630, 730, 829, 927, 1027, 1125, 1225},
            {2, 123, 222, 323, 421, 521, 619, 719, 818, 916, 1016, 1115, 1214, 1313},
            {0, 211, 313, 411, 510, 609, 708, 807, 905, 1005, 1104, 1203, 1302},
            {7, 201, 302, 401, 430, 529, 628, 727, 825, 924, 1024, 1122, 1222, 1321},
            {0, 220, 320, 419, 518, 616, 716, 814, 912, 1012, 1110, 1210, 1309},
            {0, 208, 310, 408, 508, 606, 705, 804, 902, 1001, 1031, 1129, 1229},
            {5, 128, 227, 328, 427, 527, 625, 724, 823, 921, 1020, 1119, 1218, 1317},
            {0, 216, 317, 416, 516, 614, 714, 812, 911, 1010, 1108, 1208, 1306},
            {0, 205, 305, 404, 504, 602, 702, 801, 830, 929, 1028, 1127, 1226},
            {4, 124, 223, 324, 423, 522, 621, 721, 819, 918, 1018, 1116, 1216, 1314},
            {0, 213, 314, 412, 512, 610, 710, 808, 907, 1007, 1105, 1205, 1304},
            {0, 202, 304, 402, 501, 531, 629, 729, 827, 926, 1025, 1124, 1224},
            {2, 123, 221, 322, 420, 519, 618, 717, 815, 914, 1013, 1112, 1212, 1311},
            {0, 210, 311, 410, 509, 607, 707, 805, 903, 1003, 1101, 1201, 1231},
            {6, 130, 228, 330, 429, 528, 626, 726, 824, 922, 1022, 1120, 1220, 1319},
            {0, 217, 319, 418, 517, 616, 715, 814, 912, 1011, 1110, 1209, 1308},
            {0, 206, 307, 406, 506, 604, 704, 802, 901, 930, 1029, 1128, 1227},
            {5, 126, 224, 326, 425, 524, 623, 723, 821, 920, 1019, 1118, 1217, 1315},
            {0, 214, 315, 414, 513, 612, 712, 810, 909, 1008, 1107, 1207, 1305},
            {0, 204, 305, 403, 503, 601, 701, 730, 829, 928, 1027, 1126, 1226},
            {3, 124, 223, 323, 421, 521, 619, 718, 817, 916, 1015, 1114, 1214, 1313},
            {0, 211, 313, 411, 510, 609, 708, 806, 905, 1004, 1103, 1203, 1302},
            {7, 131, 302, 401, 430, 529, 628, 727, 825, 924, 1023, 1122, 1222, 1320},
            {0, 219, 321, 420, 519, 617, 717, 815, 913, 1013, 1111, 1211, 1309},
            {0, 208, 309, 408, 507, 606, 705, 804, 902, 1001, 1031, 1129, 1229},
            {6, 127, 226, 328, 426, 526, 625, 724, 823, 921, 1020, 1119, 1218, 1317},
            {0, 215, 317, 415, 515, 614, 713, 812, 910, 1010, 1108, 1208, 1306},
            {0, 205, 306, 405, 504, 603, 702, 801, 831, 929, 1029, 1127, 1227},
            {4, 125, 224, 324, 423, 522, 621, 720, 819, 917, 1017, 1116, 1215, 1314},
            {0, 213, 314, 412, 512, 610, 709, 808, 906, 1006, 1105, 1205, 1303},
            {0, 202, 304, 402, 501, 531, 629, 728, 827, 925, 1025, 1124, 1223},
            {2, 122, 221, 323, 421, 520, 619, 718, 816, 915, 1014, 1113, 1212, 1311},
            {0, 210, 311, 409, 509, 607, 707, 805, 903, 1003, 1101, 1201, 1230},
            {7, 129, 228, 329, 428, 528, 626, 726, 824, 922, 1022, 1120, 1220, 1318},
            {0, 217, 318, 417, 517, 615, 715, 814, 912, 1011, 1110, 1209, 1308},
            {0, 206, 308, 406, 506, 605, 704, 803, 901, 1001, 1030, 1129, 1228},
            {5, 127, 225, 326, 424, 524, 622, 722, 820, 919, 1019, 1117, 1217, 1315},
            {0, 214, 315, 414, 513, 611, 711, 810, 908, 1008, 1107, 1206, 1305},
            {0, 203, 305, 403, 503, 601, 630, 730, 828, 927, 1027, 1125, 1225},
            {3, 124, 222, 324, 422, 522, 620, 719, 818, 916, 1016, 1114, 1214, 1313},
            {0, 212, 312, 411, 510, 609, 708, 806, 905, 1004, 1103, 1202, 1301},
            {8, 131, 302, 331, 430, 529, 628, 727, 825, 924, 1023, 1122, 1221, 1320},
            {0, 218, 320, 419, 519, 617, 717, 815, 913, 1013, 1111, 1211, 1309},
            {0, 208, 309, 408, 508, 606, 706, 804, 903, 1002, 1101, 1130, 1230},
            {6, 128, 227, 327, 426, 525, 624, 724, 822, 921, 1020, 1119, 1218, 1317},
            {0, 215, 317, 415, 515, 613, 713, 811, 910, 1010, 1108, 1208, 1306},
            {0, 205, 306, 405, 504, 602, 702, 731, 830, 929, 1028, 1127, 1227},
            {4, 125, 224, 325, 424, 523, 621, 721, 819, 918, 1017, 1116, 1216, 1315},
            {0, 213, 314, 412, 512, 610, 709, 808, 906, 1006, 1104, 1204, 1303},
            {0, 202, 303, 402, 501, 531, 629, 728, 827, 925, 1024, 1123, 1223},
            {3, 121, 220, 322, 421, 520, 619, 718, 816, 915, 1014, 1112, 1212, 1311},
            {0, 209, 311, 410, 509, 608, 708, 806, 904, 1004, 1102, 1202, 1231},
            {7, 130, 228, 329, 427, 527, 626, 725, 824, 922, 1022, 1120, 1220, 1318},
            {0, 217, 318, 417, 516, 615, 714, 813, 912, 1011, 1110, 1209, 1308},
            {0, 206, 308, 406, 505, 604, 703, 802, 901, 930, 1030, 1129, 1228},
            {5, 127, 225, 327, 425, 524, 623, 722, 821, 919, 1019, 1118, 1218, 1316},
            {0, 215, 315, 414, 513, 611, 711, 809, 908, 1007, 1106, 1206, 1304},
            {0, 203, 305, 403, 503, 601, 630, 730, 828, 926, 1026, 1125, 1224},
            {4, 123, 222, 324, 422, 522, 620, 719, 818, 916, 1015, 1114, 1214, 1312},
            {0, 211, 313, 412, 511, 610, 709, 807, 906, 1005, 1103, 1203, 1301},
            {8, 131, 301, 331, 429, 529, 627, 727, 825, 924, 1023, 1121, 1221, 1319},
            {0, 218, 320, 418, 518, 617, 716, 815, 913, 1013, 1111, 1211, 1309},
            {0, 207, 309, 407, 507, 606, 705, 804, 903, 1002, 1101, 1130, 1230},
            {6, 128, 227, 328, 426, 526, 624, 724, 823, 921, 1021, 1120, 1219, 1318},
            {0, 216, 317, 415, 514, 613, 712, 811, 909, 1009, 1108, 1207, 1306},
            {0, 205, 306, 405, 504, 602, 702, 731, 829, 928, 1028, 1126, 1226},
            {4, 125, 224, 325, 424, 523, 621, 721, 819, 917, 1017, 1115, 1215, 1314},
            {0, 213, 315, 413, 513, 611, 710, 809, 907, 1006, 1105, 1204, 1303},
            {10, 202, 303, 401, 501, 531, 629, 728, 827, 925, 1024, 1123, 1222, 1321},
            {0, 220, 321, 420, 520, 618, 718, 816, 915, 1014, 1112, 1212, 1310},
            {0, 209, 310, 409, 509, 607, 707, 806, 904, 1004, 1102, 1202, 1231},
            {6, 129, 228, 329, 428, 527, 626, 726, 824, 923, 1023, 1121, 1221, 1319},
            {0, 217, 318, 416, 516, 614, 714, 812, 911, 1011, 1109, 1209, 1308},
            {0, 206, 308, 406, 505, 604, 703, 802, 831, 930, 1029, 1128, 1228},
            {5, 127, 225, 327, 425, 524, 623, 722, 820, 919, 1018, 1117, 1217, 1316},
            {0, 215, 316, 415, 514, 612, 712, 810, 908, 1008, 1106, 1206, 1305},
            {0, 204, 304, 403, 503, 601, 630, 730, 828, 926, 1026, 1124, 1224},
            {3, 123, 221, 323, 422, 521, 620, 719, 818, 916, 1015, 1114, 1213, 1312},
            {0, 210, 312, 411, 511, 609, 709, 807, 906, 1005, 1103, 1203, 1301},
            {8, 131, 301, 331, 430, 529, 628, 727, 826, 925, 1024, 1122, 1222, 1320},
            {0, 219, 319, 418, 517, 616, 716, 814, 913, 1012, 1111, 1211, 1309},
            {0, 207, 309, 407, 507, 605, 705, 803, 902, 1002, 1031, 1130, 1230},
            {5, 128, 227, 328, 426, 526, 624, 723, 822, 921, 1020, 1119, 1219, 1317},
            {0, 216, 318, 416, 515, 614, 713, 811, 910, 1009, 1108, 1208, 1307},
            {0, 205, 306, 405, 504, 602, 702, 731, 829, 928, 1027, 1126, 1226},        //2000
            {4, 124, 223, 325, 423, 523, 621, 721, 819, 917, 1017, 1115, 1215, 1313},
            {0, 212, 314, 413, 512, 611, 710, 809, 907, 1006, 1105, 1204, 1303},
            {0, 201, 303, 402, 501, 531, 630, 729, 828, 926, 1025, 1124, 1223},
            {2, 122, 220, 321, 419, 519, 618, 717, 816, 914, 1014, 1112, 1212, 1310},
            {0, 209, 310, 409, 508, 607, 706, 805, 904, 1003, 1102, 1201, 1231},
            {7, 129, 228, 329, 428, 527, 626, 725, 824, 922, 1022, 1121, 1220, 1319},
            {0, 218, 319, 417, 517, 615, 714, 813, 911, 1011, 1110, 1210, 1308},
            {0, 207, 308, 406, 505, 604, 703, 801, 831, 929, 1029, 1128, 1227},
            {5, 126, 225, 327, 425, 524, 623, 722, 820, 919, 1018, 1117, 1216, 1315},
            {0, 214, 316, 414, 514, 612, 712, 810, 908, 1008, 1106, 1206, 1304},
            {0, 203, 305, 403, 503, 602, 701, 731, 829, 927, 1027, 1125, 1225},
            {4, 123, 222, 322, 421, 521, 619, 719, 817, 916, 1015, 1114, 1213, 1312},
            {0, 210, 312, 410, 510, 608, 708, 807, 905, 1005, 1103, 1203, 1301},
            {9, 131, 301, 331, 429, 529, 627, 727, 825, 924, 1024, 1122, 1222, 1320},
            {0, 219, 320, 419, 518, 616, 716, 814, 913, 1013, 1112, 1211, 1310},
            {0, 208, 309, 407, 507, 605, 704, 803, 901, 1001, 1031, 1129, 1229},
            {6, 128, 226, 328, 426, 526, 624, 723, 822, 920, 1020, 1118, 1218, 1317},
            {0, 216, 317, 416, 515, 614, 713, 811, 910, 1009, 1108, 1207, 1306},
            {0, 205, 307, 405, 505, 603, 703, 801, 830, 929, 1028, 1126, 1226},
            {4, 125, 223, 324, 423, 523, 621, 721, 819, 917, 1017, 1115, 1215, 1313},  //2020
            {0, 212, 313, 412, 512, 610, 710, 808, 907, 1006, 1105, 1204, 1303},
            {0, 201, 303, 401, 501, 530, 629, 729, 827, 926, 1025, 1124, 1223},
            {2, 122, 220, 322, 420, 519, 618, 718, 816, 915, 1015, 1113, 1213, 1311},
            {0, 210, 310, 409, 508, 606, 706, 804, 903, 1003, 1101, 1201, 1231},
            {6, 129, 228, 329, 428, 527, 625, 725, 823, 922, 1021, 1120, 1220, 1319},
            {0, 217, 319, 417, 517, 615, 714, 813, 911, 1010, 1109, 1209, 1308},
            {0, 206, 308, 407, 506, 605, 704, 802, 901, 930, 1029, 1128, 1228},
            {5, 126, 225, 326, 425, 524, 623, 722, 820, 919, 1018, 1116, 1216, 1315},
            {0, 213, 315, 414, 513, 612, 711, 810, 908, 1008, 1106, 1205, 1304},
            {0, 203, 304, 403, 502, 601, 701, 730, 829, 927, 1027, 1125, 1225},
            {3, 123, 221, 323, 422, 521, 620, 719, 818, 917, 1016, 1115, 1214, 1313},
            {0, 211, 312, 410, 509, 608, 707, 806, 905, 1004, 1103, 1203, 1301},
            {11, 131, 301, 331, 429, 528, 627, 726, 825, 923, 1023, 1122, 1222, 1320},
            {0, 219, 320, 419, 518, 616, 716, 814, 913, 1012, 1111, 1211, 1309},
            {0, 208, 310, 408, 508, 606, 705, 804, 902, 1001, 1031, 1130, 1229},
            {6, 128, 227, 328, 426, 526, 624, 723, 822, 920, 1019, 1118, 1217, 1316},
            {0, 215, 317, 416, 515, 614, 713, 811, 910, 1009, 1107, 1207, 1305},
            {0, 204, 306, 405, 504, 603, 702, 801, 830, 929, 1028, 1126, 1226},
            {5, 124, 223, 325, 423, 523, 622, 721, 820, 918, 1018, 1116, 1216, 1314},
            {0, 212, 313, 411, 511, 610, 709, 808, 906, 1006, 1105, 1204, 1303},
            {0, 201, 302, 401, 430, 530, 628, 728, 827, 925, 1025, 1124, 1223},
            {2, 122, 220, 322, 420, 519, 618, 717, 816, 914, 1014, 1113, 1212, 1311},
            {0, 210, 311, 410, 509, 607, 707, 805, 903, 1003, 1102, 1201, 1231},
            {7, 130, 229, 329, 428, 527, 625, 725, 823, 921, 1021, 1119, 1219, 1318},
            {0, 217, 319, 417, 517, 615, 714, 813, 911, 1010, 1109, 1208, 1307},
            {0, 206, 308, 406, 506, 604, 704, 802, 901, 930, 1029, 1128, 1227},
            {5, 126, 225, 326, 425, 525, 623, 723, 821, 920, 1019, 1117, 1217, 1315},
            {0, 214, 314, 413, 513, 611, 711, 810, 908, 1008, 1106, 1205, 1304},
            {0, 202, 304, 402, 502, 531, 630, 730, 828, 927, 1027, 1125, 1225},
            {3, 123, 221, 323, 421, 521, 619, 719, 817, 916, 1016, 1114, 1214, 1313},
            {0, 211, 313, 411, 510, 609, 708, 806, 905, 1005, 1103, 1203, 1302},
            {8, 201, 301, 331, 429, 528, 627, 726, 824, 923, 1022, 1121, 1221, 1320},
            {0, 219, 320, 419, 518, 616, 716, 814, 912, 1012, 1110, 1210, 1309},
            {0, 208, 309, 408, 508, 606, 705, 804, 902, 1001, 1031, 1129, 1229},
            {6, 128, 226, 328, 427, 526, 625, 724, 823, 921, 1020, 1119, 1218, 1317},
            {0, 215, 316, 415, 515, 613, 713, 811, 910, 1009, 1107, 1207, 1305},
            {0, 204, 305, 404, 504, 602, 702, 731, 830, 928, 1028, 1126, 1226},
            {4, 124, 223, 324, 423, 522, 621, 720, 819, 918, 1017, 1116, 1216, 1314},
            {0, 212, 314, 412, 512, 610, 710, 808, 907, 1006, 1105, 1205, 1304},
            {0, 202, 303, 401, 430, 530, 628, 727, 826, 924, 1024, 1123, 1223},
            {3, 121, 220, 322, 420, 519, 618, 717, 815, 914, 1013, 1112, 1212, 1311},
            {0, 209, 311, 410, 509, 607, 707, 805, 903, 1003, 1101, 1201, 1231},
            {7, 129, 228, 330, 428, 528, 626, 726, 824, 922, 1022, 1120, 1220, 1318},
            {0, 217, 318, 417, 516, 615, 714, 813, 911, 1010, 1109, 1208, 1307},
            {0, 205, 307, 406, 505, 604, 704, 802, 901, 930, 1029, 1128, 1227},
            {5, 126, 224, 326, 424, 524, 623, 722, 821, 919, 1019, 1117, 1217, 1315},
            {0, 214, 315, 414, 513, 612, 711, 810, 909, 1008, 1107, 1206, 1305},
            {0, 203, 304, 402, 502, 531, 629, 729, 828, 926, 1026, 1125, 1224},
            {4, 123, 221, 323, 421, 521, 619, 718, 817, 915, 1015, 1114, 1214, 1312},
            {0, 211, 312, 411, 510, 609, 708, 806, 905, 1004, 1103, 1203, 1301},
            {8, 131, 302, 331, 430, 529, 628, 727, 825, 924, 1023, 1122, 1221, 1320},
            {0, 219, 320, 418, 518, 616, 716, 814, 912, 1012, 1110, 1210, 1308},
            {0, 207, 309, 407, 507, 606, 705, 804, 902, 1001, 1031, 1129, 1229},
            {6, 127, 226, 327, 426, 526, 624, 724, 822, 921, 1020, 1119, 1218, 1317},
            {0, 215, 317, 415, 515, 613, 713, 812, 910, 1010, 1108, 1208, 1306},
            {0, 205, 305, 404, 503, 602, 701, 731, 829, 928, 1028, 1126, 1226},
            {4, 124, 223, 324, 423, 522, 620, 720, 818, 917, 1017, 1116, 1215, 1314},
            {0, 212, 314, 412, 512, 610, 709, 808, 906, 1006, 1105, 1204, 1303},
            {0, 202, 303, 402, 501, 531, 629, 728, 827, 925, 1025, 1123, 1223},
            {3, 122, 221, 321, 420, 519, 618, 717, 815, 914, 1013, 1111, 1211, 1310},
            {0, 209, 310, 409, 509, 607, 707, 805, 903, 1003, 1101, 1130, 1230},
            {7, 129, 227, 329, 428, 528, 626, 725, 824, 922, 1022, 1120, 1219, 1318},
            {0, 217, 318, 417, 517, 615, 715, 813, 912, 1011, 1110, 1209, 1308},
            {0, 206, 307, 405, 505, 603, 703, 802, 831, 930, 1029, 1128, 1227},
            {5, 126, 224, 326, 424, 523, 622, 722, 820, 919, 1019, 1117, 1217, 1315},
            {0, 214, 315, 414, 513, 611, 711, 809, 908, 1008, 1106, 1206, 1305},
            {0, 203, 305, 403, 503, 601, 630, 730, 828, 927, 1026, 1125, 1225},
            {4, 124, 222, 323, 421, 521, 619, 718, 817, 915, 1014, 1113, 1213, 1312},
            {0, 210, 312, 411, 510, 609, 708, 806, 904, 1004, 1102, 1202, 1301},
            {8, 130, 301, 331, 430, 529, 628, 727, 825, 924, 1023, 1121, 1221, 1320},
            {0, 218, 320, 419, 518, 617, 716, 815, 913, 1013, 1111, 1210, 1309},
            {0, 207, 308, 407, 506, 605, 705, 803, 902, 1001, 1031, 1129, 1229},
            {6, 127, 225, 327, 426, 525, 624, 723, 822, 921, 1020, 1119, 1218, 1317},
            {0, 215, 316, 415, 514, 613, 712, 811, 910, 1009, 1108, 1208, 1306},
            {0, 205, 306, 405, 504, 602, 702, 731, 830, 928, 1028, 1127, 1227},
            {4, 125, 224, 324, 423, 522, 620, 720, 818, 916, 1016, 1115, 1215, 1313},
            {0, 212, 314, 412, 512, 610, 709, 807, 906, 1005, 1104, 1204, 1302},
            {0, 201, 303, 402, 501, 531, 629, 728, 826, 925, 1024, 1123, 1222},
            {2, 121, 220, 322, 420, 520, 619, 718, 816, 915, 1014, 1112, 1212, 1310},
            {0, 209, 311, 410, 509, 608, 707, 806, 904, 1004, 1102, 1201, 1231},
            {7, 129, 228, 330, 428, 528, 626, 726, 825, 923, 1023, 1121, 1220, 1319},  //2101
            {0, 217, 319, 417, 517, 616, 715, 814, 912, 1012, 1111, 1210, 1309},       //2102
            {0, 207, 308, 407, 506, 605, 704, 803, 901, 1001, 1031, 1130, 1229},       //2103
            {5, 128, 226, 327, 425, 524, 623, 722, 821, 919, 1019, 1118, 1217, 1316},  //2104
            {0, 215, 316, 415, 514, 612, 712, 810, 908, 1008, 1107, 1206, 1305},       //2105
            {0, 204, 306, 404, 504, 602, 701, 731, 829, 927, 1027, 1125, 1225},        //2106
            {4, 124, 223, 325, 423, 523, 621, 720, 819, 917, 1016, 1115, 1214, 1313},  //2107
            {0, 212, 313, 411, 511, 609, 709, 807, 906, 1005, 1103, 1203, 1301},       //2108
            {9, 131, 302, 331, 430, 530, 628, 728, 826, 925, 1024, 1122, 1222, 1320},  //2109
            {0, 219, 320, 419, 519, 617, 717, 816, 914, 1014, 1112, 1211, 1310},       //2110
            {0, 208, 310, 408, 508, 606, 706, 805, 903, 1003, 1101, 1201, 1231},       //2111
            {6, 129, 227, 328, 426, 526, 624, 724, 822, 921, 1021, 1119, 1219, 1318},  //2112
            {0, 216, 318, 416, 515, 614, 713, 811, 910, 1010, 1108, 1208, 1307},       //2113
            {0, 206, 307, 406, 505, 603, 703, 801, 830, 929, 1028, 1127, 1227},        //2114
            {4, 126, 225, 326, 425, 524, 622, 722, 820, 918, 1018, 1116, 1216, 1315},  //2115
            {0, 214, 314, 413, 512, 611, 710, 809, 907, 1006, 1105, 1204, 1303},       //2116
            {0, 202, 303, 402, 502, 531, 630, 729, 828, 926, 1025, 1124, 1223},        //2117
            {3, 122, 220, 322, 421, 520, 619, 719, 817, 916, 1015, 1113, 1213, 1311},  //2118
            {0, 210, 311, 410, 509, 608, 708, 806, 905, 1004, 1103, 1202, 1301},       //2119
            {7, 130, 229, 329, 428, 527, 626, 725, 824, 923, 1022, 1121, 1220, 1319},  //2120
            {0, 217, 319, 417, 517, 615, 715, 813, 912, 1011, 1110, 1210, 1309},       //2121
            {0, 207, 308, 407, 506, 605, 704, 802, 901, 930, 1030, 1129, 1229},        //2122
            {5, 127, 226, 328, 426, 525, 624, 723, 821, 920, 1019, 1118, 1218, 1317},  //2123
            {0, 215, 316, 414, 514, 612, 712, 810, 908, 1008, 1106, 1206, 1305},       //2124
            {0, 203, 305, 404, 503, 602, 701, 731, 829, 927, 1027, 1125, 1225},        //2125
            {4, 123, 222, 324, 423, 522, 621, 720, 819, 917, 1016, 1115, 1214, 1313},  //2126
            {0, 211, 313, 412, 511, 610, 710, 808, 906, 1006, 1104, 1204, 1302},       //2127
            {11, 201, 301, 331, 429, 529, 628, 727, 826, 924, 1024, 1122, 1222, 1320}, //2128
            {0, 219, 320, 419, 518, 617, 716, 815, 914, 1013, 1112, 1211, 1310},       //2129
            {0, 208, 310, 408, 508, 606, 705, 804, 903, 1002, 1101, 1201, 1230},       //2130
            {6, 129, 227, 329, 427, 527, 625, 724, 823, 921, 1021, 1120, 1220, 1318},  //2131
            {0, 217, 317, 416, 515, 614, 713, 811, 910, 1009, 1108, 1208, 1306},       //2132
            {0, 205, 307, 405, 505, 603, 703, 801, 830, 928, 1028, 1127, 1226},        //2133
            {5, 125, 224, 326, 424, 524, 622, 722, 820, 918, 1018, 1116, 1216, 1314},  //2134
            {0, 213, 315, 413, 513, 612, 711, 809, 908, 1007, 1106, 1205, 1304},       //2135
            {0, 202, 303, 401, 501, 531, 629, 729, 827, 926, 1025, 1124, 1223},        //2136
            {2, 122, 220, 322, 420, 520, 618, 718, 817, 915, 1015, 1113, 1213, 1311},  //2137
            {0, 210, 311, 410, 509, 608, 707, 806, 904, 1004, 1103, 1202, 1301},       //2138
            {7, 130, 301, 330, 429, 528, 626, 726, 824, 923, 1023, 1122, 1221, 1320},  //2139
            {0, 218, 319, 417, 517, 615, 714, 813, 911, 1011, 1110, 1209, 1308},       //2140
            {0, 207, 308, 407, 506, 605, 704, 802, 901, 930, 1030, 1128, 1228},        //2141
            {5, 127, 226, 327, 426, 525, 624, 723, 821, 919, 1019, 1117, 1217, 1316},  //2142
            {0, 215, 316, 415, 515, 613, 713, 811, 909, 1008, 1107, 1206, 1305},       //2143
            {0, 204, 304, 403, 503, 602, 701, 730, 829, 927, 1027, 1125, 1224},        //2144
            {4, 123, 222, 323, 422, 522, 620, 720, 818, 917, 1016, 1115, 1214, 1313},  //2145
            {0, 211, 312, 411, 511, 609, 709, 807, 906, 1006, 1104, 1204, 1302},       //2146
            {0, 201, 302, 331, 430, 529, 628, 728, 826, 925, 1025, 1123, 1223},        //2147
            {1, 121, 220, 320, 419, 518, 616, 716, 814, 913, 1013, 1111, 1211, 1310},  //2148
            {0, 208, 310, 408, 508, 606, 705, 804, 902, 1002, 1031, 1130, 1230},       //2149
            {6, 129, 227, 329, 427, 527, 625, 724, 822, 921, 1020, 1119, 1219, 1318},  //2150
    };

    /**
     * serialVersionUID
     */
    private static final long serialVersionUID = 7241031233810655166L;

    // ------------------------ 成员变量 --------------------------------

    // 农历年，和公历可能不一样
    private int lyear;
    // 农历月，范围1-12
    private int lmonth;
    // 农历日期
    private int ldate;
    // 是否为闰月日期
    private boolean isLeapMonth = false;
    // 农历这年闰月，如果不闰月，默认为0
    private int leapMonth = 0;
    // 公历日期，公历月份范围：0-11
    private GregorianCalendar solar = new GregorianCalendar();

    // ------------------------ 构造方法 --------------------------------

    /**
     * 默认构造
     */
    public LunarCalendar() {
        computeBySolarDate(solar.get(Calendar.YEAR), solar.get(Calendar.MONTH), solar.get(Calendar.DATE));
    }

    /**
     * 通过农历年、月、日构造
     *
     * @param lunarYear       农历年
     * @param lunarMonth      农历月份,范围1-12
     * @param lunarDate       农历日
     * @param isLeapMonth     是否闰月
     */
    public LunarCalendar(int lunarYear, int lunarMonth, int lunarDate, boolean isLeapMonth) {
        computeByLunarDate(lunarYear, lunarMonth, lunarDate, isLeapMonth);
    }

    /**
     * 通过公历构造
     *
     * @param calendar 　公历日期
     */
    public LunarCalendar(Calendar calendar) {
        computeBySolarDate(calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH), calendar.get(Calendar.DATE));
    }

    // ------------------------ 静态方法 --------------------------------

    /**
     * 计算两个农历日期之差
     *
     * @param lc1   　农历１
     * @param lc2   　农历２
     * @param field 　计算的维度，比如按月,天等
     * @return 具体的差值
     */
    public static long luanrDiff(LunarCalendar lc1, LunarCalendar lc2, int field) {
        return solarDiff(lc1.getSolar(), lc2.getSolar(), field);
    }

    /**
     * 公历转农历
     *
     * @param solar 　公历日期
     * @return 农历日期
     */
    public static LunarCalendar solar2Lunar(Calendar solar) {
        LunarCalendar ret = new LunarCalendar();
        ret.computeBySolarDate(solar.get(Calendar.YEAR), solar.get(Calendar.MONTH), solar.get(Calendar.DATE));
        return ret;
    }

    /**
     * 农历转公历
     *
     * @param lunarYear   　农历年
     * @param lunarMonth  　农历月，从１开始
     * @param LunarDate   　农历日
     * @param isLeapMonth 　是否润月
     * @return 公历日期
     */
    public static Calendar lunar2Solar(int lunarYear, int lunarMonth, int LunarDate, boolean isLeapMonth) {
        LunarCalendar ret = new LunarCalendar();
        ret.computeByLunarDate(lunarYear, lunarMonth, LunarDate, isLeapMonth);
        return ret.getSolar();
    }

    /**
     * 获取农历日的表示
     *
     * @param lunarDay 　农历日数值表示
     * @return 农历日传统字符表示
     */
    public static String getDayName(int lunarDay) {
        return LunarDayName[lunarDay - 1];
    }

    /**
     * 获取农历月份
     *
     * @param lunarMonth 　农历月数值表示
     * @return 农历月传统字符表示
     */
    public static char getMonthName(int lunarMonth) {
        return LunarMonthName[lunarMonth - 1];
    }

    /**
     * 获取农历年份
     *
     * @param lunarYear 　农历年数值表示
     * @return 农历年传统字符表示
     */
    public static String getYearName(int lunarYear) {
        StringBuilder sb = new StringBuilder();
        sb.append(LunarYearName[lunarYear / 1000]);
        sb.append(LunarYearName[lunarYear % 1000 / 100]);
        sb.append(LunarYearName[lunarYear % 100 / 10]);
        sb.append(LunarYearName[lunarYear % 10]);
        return sb.toString();
    }

    /**
     * 判断两个整数所代表公历日期的差值<br>
     * 一年按365天计算，一个月按30天计算<br>
     *
     * @param solarCode1 　农历日期代码
     * @param solarCode2 　农历日期代码
     * @param field      　差值单位
     * @return 差值
     */
    public static long solarDateCodesDiff(int solarCode1, int solarCode2, int field) {
        GregorianCalendar c1 = new GregorianCalendar(solarCode1 / 10000, solarCode1 % 10000 / 100 - 1,
                solarCode1 % 10000 % 100);
        GregorianCalendar c2 = new GregorianCalendar(solarCode2 / 10000, solarCode2 % 10000 / 100 - 1,
                solarCode2 % 10000 % 100);
        return solarDiff(c1, c2, field);
    }

    /**
     * 求两个公历日期之差，field可以为年月日，时分秒<br>
     * 一年按365天计算，一个月按30天计算<br>
     *
     * @param solar1 　历日期
     * @param solar2 　历日期
     * @param field  差值单位
     * @return 差值
     */
    public static long solarDiff(Calendar solar1, Calendar solar2, int field) {
        long t1 = solar1.getTimeInMillis();
        long t2 = solar2.getTimeInMillis();
        switch (field) {
            case Calendar.SECOND:
                return (long) Math.rint(Double.valueOf(t1 - t2) / Double.valueOf(1000));
            case Calendar.MINUTE:
                return (long) Math.rint(Double.valueOf(t1 - t2) / Double.valueOf(60 * 1000));
            case Calendar.HOUR:
                return (long) Math.rint(Double.valueOf(t1 - t2) / Double.valueOf(3600 * 1000));
            case Calendar.DATE:
                return (long) Math.rint(Double.valueOf(t1 - t2) / Double.valueOf(24 * 3600 * 1000));
            case Calendar.MONTH:
                return (long) Math.rint(Double.valueOf(t1 - t2) / Double.valueOf(30 * 24 * 3600 * 1000));
            case Calendar.YEAR:
                return (long) Math.rint(Double.valueOf(t1 - t2) / Double.valueOf(365 * 24 * 3600 * 1000));
            default:
                return -1;
        }
    }

    /**
     * 返回传统天干地支年名称
     *
     * @param y 农历年
     * @return 传统农历年份的表示
     */
    public static String getTraditionalYearName(int y) {
        // 1804年是甲子年
        y = y - 1804;
        return ("" + LunarGan[y % 10] + LunarZhi[y % 12] + "年");
    }

    /**
     * 获取生肖名
     *
     * @param y 　农历年
     * @return 生肖名
     */
    public static char getAnimalYearName(int y) {
        return LunarAnimalName[(y - 4) % 12];
    }

    // ------------------------ 成员方法 --------------------------------

    /**
     * 一个简单的二分查找，返回查找到的元素坐标，用于查找农历二维数组信息
     *
     * @param array 　数组
     * @param n     　待查询数字
     * @return 查到的坐标
     */
    private static int binSearch(int[] array, int n) {
        if (null == array || array.length == 0) {
            return -1;
        }
        int min = 0, max = array.length - 1;
        if (n <= array[min]) {
            return min;
        } else if (n >= array[max]) {
            return max;
        }
        while (max - min > 1) {
            int newIndex = (max + min) / 2; // 二分
            if (array[newIndex] > n) { // 取小区间
                max = newIndex;
            } else if (array[newIndex] < n) {// 取大区间
                min = newIndex;
            } else { // 相等，直接返回下标
                return newIndex;
            }
        }
        if (array[max] == n) {
            return max;
        } else if (array[min] == n) {
            return min;
        } else {
            return min; // 返回 较小的一个
        }
    }

    /**
     * 日期增加,和<code>GregorianCalendar.add</code>类似
     *
     * @param field  　单位
     * @param amount 数值
     * @see GregorianCalendar
     */
    public void add(int field, int amount) {
        this.getSolar().add(field, amount);
        this.computeBySolarDate(this.getSolar().get(Calendar.YEAR), this.getSolar().get(Calendar.MONTH),
                this.getSolar().get(Calendar.DATE));
    }

    /**
     * 返回农历日期，不包含年份
     *
     * @param showLeap 　是否显示闰月的闰字
     * @return 农历日期
     */
    public String getLunar(boolean showLeap) {
        if (this.lmonth < 1 || this.lmonth > 12 || this.ldate < 1 || this.ldate > 30) {
            throw new LunarException("Wrong lunar ldate: " + lmonth + " " + ldate);
        }
        if (showLeap) {
            return (this.isLeapMonth() ? "闰" : "") + getMonthName(this.lmonth) + "月"
                    + getDayName(this.ldate);
        } else {
            return getMonthName(this.lmonth) + "月" + getDayName(this.ldate);
        }
    }

    @Override
    public String toString() {
        if (this.lyear < MINI_YEAR || this.lyear > MAX_YEAR || this.lmonth < 1 || this.lmonth > 12 || this.ldate < 1
                || this.ldate > 30) {
            return "Wrong lunar date: " + lyear + " " + lmonth + " " + ldate;
        }
        return getYearName(this.lyear) + "年" + (this.isLeapMonth() ? "闰" : "") + getMonthName(this.lmonth) + "月"
                + getDayName(this.ldate);
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        LunarCalendar that = (LunarCalendar) o;

        if (lyear != that.lyear) return false;
        if (lmonth != that.lmonth) return false;
        if (ldate != that.ldate) return false;
        return isLeapMonth == that.isLeapMonth;
    }

    @Override
    public int hashCode() {
        int result = lyear;
        result = 31 * result + lmonth;
        result = 31 * result + ldate;
        result = 31 * result + (isLeapMonth ? 1 : 0);
        return result;
    }

    /**
     * 返回中国农历的全名
     *
     * @return String
     */
    public String getFullLunarName() {
        return this.toString() + " " + getTraditionalYearName(this.lyear) + " " + getAnimalYearName(this.lyear);
    }

    /**
     * 创建LunarInfo中某一年的一列公历日历编码<br>
     * 公历日历编码：年份+月份+天，用于查询某个公历日期在某个LunarInfo列的哪一个区间<br>
     *
     * @param solarYear 年份
     * @return 公历日历编码
     */
    private int[] builderSolarCodes(int solarYear) {
        if (solarYear < MINI_YEAR || solarYear > MAX_YEAR) {
            throw new LunarException("Illegal solar year: " + solarYear);
        }
        int lunarIndex = solarYear - MINI_YEAR;
        int[] solarCodes = new int[LUNAR_INFO[lunarIndex].length];
        for (int i = 0; i < solarCodes.length; i++) {
            if (0 == i) { // 第一个数表示闰月，不用更改
                solarCodes[i] = LUNAR_INFO[lunarIndex][i];
            } else if (1 == i) {
                if (LUNAR_INFO[lunarIndex][1] > 999) {
                    // 这年农历一月一日对应的公历实际是上一年的
                    solarCodes[i] = (solarYear - 1) * 10000 + LUNAR_INFO[lunarIndex][i];
                } else {
                    solarCodes[i] = solarYear * 10000 + LUNAR_INFO[lunarIndex][i];
                }
            } else {
                solarCodes[i] = solarYear * 10000 + LUNAR_INFO[lunarIndex][i];
            }
        }
        return solarCodes;
    }

    /**
     * 通过给定的农历日期，计算公历日期
     *
     * @param lunarYear   　农历年
     * @param lunarMonth  　农历月，从１开始
     * @param lunarDate   　农历日期
     * @param isleapMonth 　是否为闰月
     */
    private void computeByLunarDate(final int lunarYear, final int lunarMonth, final int lunarDate, final boolean isleapMonth) {
        if (lunarYear < MINI_YEAR || lunarYear > MAX_YEAR) {
            throw new LunarException("LunarYear must in (" + MINI_YEAR + "," + MAX_YEAR + ")");
        }
        this.lyear = lunarYear;
        this.lmonth = lunarMonth;
        this.ldate = lunarDate;
        int solarMontDate = LUNAR_INFO[lunarYear - MINI_YEAR][lunarMonth];
        leapMonth = LUNAR_INFO[lunarYear - MINI_YEAR][0];
        if (leapMonth != 0 && (lunarMonth > leapMonth || (lunarMonth == leapMonth && isleapMonth))) {
            // 闰月，且当前农历月大于闰月月份，取下一个月的LunarInfo码
            // 闰月，且当前农历月等于闰月月份，并且此农历月为闰月，取下一个月的LunarInfo码
            solarMontDate = LUNAR_INFO[lunarYear - MINI_YEAR][lunarMonth + 1];
        }
        this.getSolar().set(Calendar.YEAR, lunarYear);
        this.getSolar().set(Calendar.MONTH, (solarMontDate / 100) - 1);
        this.getSolar().set(Calendar.DATE, solarMontDate % 100);
        this.add(Calendar.DATE, lunarDate - 1);
    }

    /**
     * 通过给定公历日期，计算农历日期
     *
     * @param solarYear  公历年
     * @param solarMonth 公历月，0-11
     * @param solarDate  公历日
     */
    private void computeBySolarDate(final int solarYear, final int solarMonth, final int solarDate) {
        if (solarYear < MINI_YEAR || solarYear > MAX_YEAR) {
            throw new LunarException("Illegal solar year: " + solarYear);
        }
        int solarCode = solarYear * 10000 + 100 * (1 + solarMonth) + solarDate; // 公历码
        leapMonth = LUNAR_INFO[solarYear - MINI_YEAR][0];
        int[] solarCodes = builderSolarCodes(solarYear);
        int newMonth = binSearch(solarCodes, solarCode);
        if (-1 == newMonth) {
            throw new LunarException("No lunarInfo found by solarCode: " + solarCode);
        }
        int xdate = Long.valueOf(solarDateCodesDiff(solarCode, solarCodes[newMonth], Calendar.DATE)).intValue();
        if (0 == newMonth) {// 在上一年
            int preYear = solarYear - 1;
            short[] preSolarCodes = LUNAR_INFO[preYear - MINI_YEAR];
            // 取上年农历12月1号公历日期码
            int nearSolarCode = preSolarCodes[preSolarCodes.length - 1]; // 上一年12月1号
            // 下一年公历1月表示为了13月，这里做翻译，并计算出日期码
            nearSolarCode = (nearSolarCode / 100 == 13 ? preYear + 1 : preYear) * 10000
                    + (nearSolarCode / 100 == 13 ? nearSolarCode - 1200 : nearSolarCode);
            if (nearSolarCode > solarCode) {// 此公历日期在上一年农历12月1号，之前，即在上年农历11月内
                newMonth = 11;
                // 取农历11月的公历码
                nearSolarCode = preYear * 10000 + preSolarCodes[preSolarCodes.length - 2];
            } else {// 此公历日期在上一年农历12月内
                newMonth = 12;
            }
            xdate = Long.valueOf(solarDateCodesDiff(solarCode, nearSolarCode, Calendar.DATE)).intValue();
            if (xdate < 0) {
                throw new LunarException("Wrong solarCode: " + solarCode);
            }
            this.ldate = 1 + xdate;
            this.lyear = preYear;
            this.lmonth = newMonth;
            this.isLeapMonth = false; // 农历12月不可能为闰月
        } else if (solarCodes.length == newMonth + 1 && xdate >= 30) {// 在下一年(公历12月只有30天)
            newMonth = 1; // 农历肯定是1月
            // 取下一年的公历日期码
            short[] nextSolarCodes = LUNAR_INFO[solarYear + 1 - MINI_YEAR];
            // 取下一年农历1月1号公历日期码
            int nearSolarCode = solarYear * 10000 + nextSolarCodes[1]; // 下一年农历1月1号公历日期码
            xdate = Long.valueOf(solarDateCodesDiff(solarCode, nearSolarCode, Calendar.DATE)).intValue();
            if (xdate < 0) {
                throw new LunarException("Wrong solarCode: " + solarCode);
            }
            this.ldate = 1 + xdate;
            this.lyear = solarYear + 1; // 农历年到了下一年
            this.lmonth = newMonth;
            this.isLeapMonth = false; // 农历1月不可能为闰月
        } else {
            if (xdate < 0) {
                throw new LunarException("Wrong solarCode: " + solarCode);
            }
            this.ldate = 1 + xdate;
            this.lyear = solarYear;
            this.isLeapMonth = 0 != leapMonth && (leapMonth + 1 == newMonth);
            if (0 != leapMonth && leapMonth < newMonth) {
                this.lmonth = newMonth - 1;
            } else {
                this.lmonth = newMonth;
            }
        }
        this.getSolar().set(Calendar.YEAR, solarYear);
        this.getSolar().set(Calendar.MONTH, solarMonth);
        this.getSolar().set(Calendar.DATE, solarDate);
    }

    // ------------------------ getter and sette --------------------------------

    public int getLyear() {
        return lyear;
    }

    public void setLyear(int lyear) {
        this.lyear = lyear;
    }

    public int getLmonth() {
        return lmonth;
    }

    public void setLmonth(int lmonth) {
        this.lmonth = lmonth;
    }

    public int getLdate() {
        return ldate;
    }

    public void setLdate(int ldate) {
        this.ldate = ldate;
    }

    public int getLeapMonth() {
        return leapMonth;
    }

    public GregorianCalendar getSolar() {
        return solar;
    }

    public void setSolar(GregorianCalendar solar) {
        this.solar = solar;
    }

    public boolean isLeapMonth() {
        return isLeapMonth;
    }

    public void setLeapMonth(int leapMonth) {
        this.leapMonth = leapMonth;
    }

    public void setLeapMonth(boolean isLeapMonth) {
        this.isLeapMonth = isLeapMonth;
    }

    /**
     * 农历日期异常
     *
     * @author joel
     */
    public static class LunarException extends RuntimeException {

        /**
         * serialVersionUID
         */
        private static final long serialVersionUID = 3274596943314243191L;

        private String message;

        // constructor
        public LunarException(String message) {
            super(message);
            this.message = message;
        }

        public LunarException() {
            super();
        }

        public LunarException(String message, Throwable t) {
            super(message, t);
            this.message = message;
        }

        public LunarException(Throwable t) {
            super(t);
        }

        // getter and setter
        public String getMessage() {
            return message;
        }

        public void setMessage(String message) {
            this.message = message;
        }
    }
}